package com.alingrad.android.froyoengine.input;

import javax.microedition.khronos.opengles.GL10;

import android.view.KeyEvent;
import android.view.MotionEvent;

import com.alingrad.android.froyoengine.GameRenderer;
import com.alingrad.android.froyoengine.tree.TreeNode;

public class InputState extends TreeNode {
	private boolean mKeysDown[];
	private TouchState[] mTouch;
	
	public InputState() {
		super();
		mKeysDown = new boolean[KeyEvent.getMaxKeyCode()];
		mTouch = new TouchState[4];
		for (int i = 0; i < mTouch.length; i++)
			mTouch[i] = new TouchState();
	}
	
	@Override
	public void update(long delta) {
		for (TouchState touch : mTouch)
			touch.update(delta);
	}

	public void copy(InputState other) {
		for (int i = 0; i < mKeysDown.length; i++) {
			mKeysDown[i] = other.mKeysDown[i];
		}
		for (int i = 0; i < mTouch.length; i++) {
			mTouch[i].mX = other.mTouch[i].mX;
			mTouch[i].mY = other.mTouch[i].mY;
			mTouch[i].mAction = other.mTouch[i].mAction;
			mTouch[i].mActive = other.mTouch[i].mActive;
		}
	}
	
	public boolean isKeyDown(int keyCode) {
		return mKeysDown[keyCode];
	}
	
	public TouchState getTouchState(int index) {
		return mTouch[index];
	}
	
	public TouchState getTouchStateFromId(int pointerId) {
		int index = getIndex(pointerId);
		if (index == -1)
			return null;
		return mTouch[index];
	}
	
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		mKeysDown[keyCode] = true;
		return true;
	}
	
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		mKeysDown[keyCode] = false;
		return true;
	}
	
	public int getIndex(int pointerId) {
		for (int i = 0; i < mTouch.length; i++) {
			if (mTouch[i].mPointerId == pointerId)
				return i;
		}
		return -1;
	}
	
	public int findAvailableIndex() {
		for (int i = 0; i < mTouch.length; i++) {
			if (!mTouch[i].isActive())
				return i;
		}
		return -1;
	}
	
	public boolean onTouchEvent(MotionEvent event) {
		int pointerIndex;
		int index;
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			mTouch[0].set(event.getX(), GameRenderer.VIEW_HEIGHT - event.getY(), MotionEvent.ACTION_DOWN);
			mTouch[0].mPointerId = event.getPointerId(0);
			break;
		case MotionEvent.ACTION_UP:
			index = getIndex(event.getPointerId(0));
			mTouch[index].set(event.getX(0), GameRenderer.VIEW_HEIGHT - event.getY(0), MotionEvent.ACTION_UP);
			break;
		case MotionEvent.ACTION_CANCEL:
			index = getIndex(event.getPointerId(0));
			mTouch[index].set(0, 0, MotionEvent.ACTION_CANCEL);
		case MotionEvent.ACTION_POINTER_DOWN:
			pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
			index = findAvailableIndex();
			if (index == -1)
				break;
			mTouch[index].set(event.getX(pointerIndex), event.getY(pointerIndex), MotionEvent.ACTION_DOWN);
			mTouch[index].mPointerId = event.getPointerId(pointerIndex);
			break;
		case MotionEvent.ACTION_POINTER_UP:
			pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
			index = getIndex(event.getPointerId(pointerIndex));
			mTouch[index].set(event.getX(pointerIndex), event.getY(pointerIndex), MotionEvent.ACTION_UP);
			break;
		case MotionEvent.ACTION_MOVE:
			for (int i = 0; i < mTouch.length; i++) {
				if (mTouch[i].isActive()) {
					pointerIndex = event.findPointerIndex(mTouch[i].mPointerId);
					mTouch[i].set(event.getX(pointerIndex), GameRenderer.VIEW_HEIGHT - event.getY(pointerIndex), MotionEvent.ACTION_MOVE);
				}
			}
			break;
		}
		return true;
	}
	
	@Override
	public void load(GL10 gl) {
	}

	@Override
	public boolean isAlive() {
		return true;
	}
}
